using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace Unbound.Unbinders
{
	internal class ComplexUnbinder : ISpecificUnbinder
	{
		readonly ITypeDescriptor _typeDescriptor;
		readonly IUnbinder _unbinder;

		public ComplexUnbinder(ITypeDescriptor typeDescriptor, IUnbinder unbinder)
		{
			_typeDescriptor = typeDescriptor;
			_unbinder = unbinder;
		}

		public void Unbind(IUnbindingRequest request)
		{
			var propertyDescriptors = GetPropertiesToUnbind(request);

			foreach (var descriptor in propertyDescriptors)
			{
				UnbindProperty(request, descriptor);
			}
		}

		void UnbindProperty(IUnbindingRequest request, PropertyDescriptor descriptor)
		{
			var value = descriptor.GetValue(request.Source);
			var name = descriptor.Name;
			var modifiedPrefix = GetModifiedPrefix(request.Prefix, name);

			var serializedComponent = _unbinder.Unbind(value, modifiedPrefix);
			request.Result.Merge(serializedComponent);
		}

		IEnumerable<PropertyDescriptor> GetPropertiesToUnbind(IUnbindingRequest request)
		{
			var result = _typeDescriptor
				.GetProperties(request.Source.GetType())
				.Cast<PropertyDescriptor>()
				.Where(x => !request.PropertiesToSkip.Contains(x.Name));

			return result;
		}

		public bool AppropriatelyUnbinds(IUnbindingRequest request)
		{
			return true;
		}

		static string GetModifiedPrefix(string prefix, string name)
		{
			if (!string.IsNullOrEmpty(prefix))
				return prefix + "." + name;
			return name;
		}
	}
}